#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <bpf/libbpf.h>
#include "open.skel.h"
struct event
{
    unsigned int ret;
    unsigned int pid;   // 进程ID
    unsigned int uid;   // 用户ID
    unsigned int flags; // 打开标志（如O_RDONLY, O_WRONLY等）
    char comm[16];      // 进程名
    char fname[128];    // 文件名
};
// 在handle_event中添加
static const char *decode_flags(int flags)
{
    static char buf[32];

    buf[0] = '\0';

    if (flags & O_RDONLY)
        strcat(buf, "RDONLY|");
    if (flags & O_WRONLY)
        strcat(buf, "WRONLY|");
    if (flags & O_RDWR)
        strcat(buf, "RDWR|");
    if (flags & O_CREAT)
        strcat(buf, "CREAT|");
    if (flags & O_EXCL)
        strcat(buf, "EXCL|");
    if (flags & O_TRUNC)
        strcat(buf, "TRUNC|");
    if (flags & O_APPEND)
        strcat(buf, "APPEND|");

    // 移除最后一个'|'
    if (buf[0] != '\0')
        buf[strlen(buf) - 1] = '\0';

    return buf;
}

/*
 * 事件处理回调函数
 */
static int handle_event(void *ctx, void *data, size_t size)
{
    const struct event *e = data;
    time_t t = time(NULL);
    struct tm *tm = localtime(&t);
    char ts[32];

    strftime(ts, sizeof(ts), "%H:%M:%S", tm);

    if (e->flags & (O_WRONLY | O_CREAT))
    {
        printf("%-8s %-6d %-6d %-16s %-16s %s\n",
               ts, e->pid, e->uid, e->comm, decode_flags(e->flags), e->fname);
    }
    return 0;
}

static int handle_exit_event(void *ctx, void *data, size_t size)
{
    const struct event *e = data;
    time_t t = time(NULL);
    struct tm *tm = localtime(&t);
    char ts[32];

    strftime(ts, sizeof(ts), "%H:%M:%S", tm);

    printf("%-8s %-6d %-6d %-16s %-16s %s\n",
           ts, e->pid, e->uid, e->comm, "Closed", e->fname);
    return 0;
}

int main(int argc, char **argv)
{
    struct ring_buffer *rb = NULL;
    struct ring_buffer *exit_rb = NULL;
    struct open_bpf *skel;
    int err;

    // 打开BPF程序
    skel = open_bpf__open();
    if (!skel)
    {
        fprintf(stderr, "无法打开BPF骨架\n");
        return 1;
    }

    // 加载和验证BPF程序
    err = open_bpf__load(skel);
    if (err)
    {
        fprintf(stderr, "无法加载BPF程序\n");
        goto cleanup;
    }

    // 附加跟踪点
    err = open_bpf__attach(skel);
    if (err)
    {
        fprintf(stderr, "无法附加BPF程序\n");
        goto cleanup;
    }

    // 设置环形缓冲区
    rb = ring_buffer__new(bpf_map__fd(skel->maps.events), handle_event, NULL, NULL);
    if (!rb)
    {
        err = -1;
        fprintf(stderr, "无法创建环形缓冲区\n");
        goto cleanup;
    }
    exit_rb = ring_buffer__new(bpf_map__fd(skel->maps.exit_events), handle_exit_event, NULL, NULL);
    if (!exit_rb)
    {
        err = -1;
        fprintf(stderr, "无法创建环形缓冲区\n");
        goto cleanup;
    }
    // 打印表头（移除了RET列，添加了FLAGS列）
    printf("%-8s %-6s %-6s %-16s %-6s %s\n",
           "TIME", "PID", "UID", "COMM", "FLAGS\t\t", "\t\tFILENAME");

    // 事件循环
    while (1)
    {
        err = 0;

        if (rb)
        {
            int rb_err = ring_buffer__poll(rb, 100); // 100ms超时
            if (rb_err < 0 && rb_err != -EAGAIN)
            {
                fprintf(stderr, "进入事件轮询错误: %d\n", rb_err);
                err = rb_err;
            }
        }

        if (exit_rb)
        {
            int rb_err = ring_buffer__poll(exit_rb, 100);
            if (rb_err < 0 && rb_err != -EAGAIN)
            {
                fprintf(stderr, "退出事件轮询错误: %d\n", rb_err);
                err = rb_err;
            }
        }

        if (err == -EINTR)
        {
            err = 0;
            break;
        }
        if (err < 0)
        {
            break;
        }
    }

cleanup:
    if (rb)
        ring_buffer__free(rb);
    if (exit_rb)
        ring_buffer__free(exit_rb);
    open_bpf__destroy(skel);
    return err;
}